package org

import (
	"context"
	"errors"
	"fmt"
	"git.mycaigou.com/gfyx/common/usermetadata"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/constants"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/errcode"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/dto/base"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/area"
	baseOrg "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/org"
	profitRepo "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/profit"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/user"
	pb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/base"
	"git.myscrm.cn/golang/stark/v4"
	"github.com/google/uuid"
	"strings"
	"time"
)

type orgService struct {
	orgRepo        baseOrg.OrgRepositoryIface
	userRepo       user.UserRepositoryIface
	userOrgRepo    user.UserOrgRepositoryIface
	areaConfigRepo area.AreaConfigRepositoryIface
	profitRepo     profitRepo.ProfitRepositoryIface
}

// NewOrgService 构造函数
func NewOrgService(orgRepo baseOrg.OrgRepositoryIface, userRepo user.UserRepositoryIface, userOrgRepo user.UserOrgRepositoryIface,
	areaConfigRepo area.AreaConfigRepositoryIface, profitRepo profitRepo.ProfitRepositoryIface) OrgServiceIface {
	return &orgService{
		orgRepo:        orgRepo,
		userRepo:       userRepo,
		userOrgRepo:    userOrgRepo,
		areaConfigRepo: areaConfigRepo,
		profitRepo:     profitRepo,
	}
}

// Save 新增/更新组织数据
func (s *orgService) Save(ctx context.Context, org *baseOrg.GfyOrganizationPo, orgAreaCodes []string) (int64, error) {
	// 0. 检查是否存在根组织
	if org.ParentId == 0 {
		isRootOrg, err := s.orgRepo.CheckRootOrg(ctx)
		if err != nil {
			return 0, err
		}

		if isRootOrg == false {
			stark.Logger.Infof(ctx, "org-save-info, org: %+v", org)
			return 0, errcode.OrgParentNotExist
		}
	}

	// 1. 检查父级id是否存在
	parentOrg, err := s.orgRepo.GetById(ctx, org.ParentId)
	if err != nil {
		return 0, err
	} else if org.ParentId > 0 && (parentOrg == nil || parentOrg.Id == 0) {
		return 0, errcode.OrgParentNotExist
	}

	// 2. 拼接fullname
	if parentOrg.FullName != "" {
		org.FullName = fmt.Sprintf("%s-%s", parentOrg.FullName, org.Name)
	} else {
		org.FullName = org.Name
	}

	// 更新子组织的full_name字段的值
	subOrgList, err := s.upgradeSubOrgFullName(ctx, org.Id, org.FullName)
	if err != nil {
		return 0, err
	}
	for _, item := range subOrgList {
		fmt.Printf("subOrg: %#v\n", item)
	}

	// 3.parentGuid、guid赋值
	org.ParentGuid, org.Guid = parentOrg.Guid, uuid.New().String()

	// 4. 检查同名
	cOrg, err := s.orgRepo.CheckFullName(ctx, org.Id, org.FullName)
	if err != nil {
		return 0, err
	} else if cOrg != nil && cOrg.Id != 0 {
		return 0, errcode.OrgNameExist
	}

	// 5. 检查部门ID是否存在
	if org.Id != 0 {
		existedOrg, err := s.orgRepo.GetById(ctx, org.Id)
		if err != nil {
			return 0, err
		} else if existedOrg.Id == 0 {
			return 0, errcode.OrgIdNotExist
		}
		org.Guid = existedOrg.Guid
	}
	// 区域权限判断
	orgAreaCodes2 := []string{}
	if len(orgAreaCodes) > 0 {
		dataAuth, err := s.getDataAuthProvinceCodes(ctx)
		if err != nil {
			stark.Logger.Errorf(ctx, "Save-getDataAuthProvinceCodes err:%+v", err)
			return 0, err
		}
		if dataAuth == nil {
			stark.Logger.Errorf(ctx, "Save-getDataAuthProvinceCodes 数据权限获取异常")
			return 0, errors.New("数据权限获取异常")
		}

		areaList, err := s.areaConfigRepo.GetAreaInfoByItemCode(ctx, orgAreaCodes)
		if err != nil {
			stark.Logger.Errorf(ctx, "Save-GetAreaInfoByItemCode err:%+v", err)
			return 0, errors.New("区域获取异常")
		}
		if areaList == nil {
			stark.Logger.Errorf(ctx, "Save-getDataAuthProvinceCodes orgAreaCodes empty")
			return 0, errors.New("区域不存在")
		}
		if dataAuth.RegionType == 2 && len(dataAuth.ProvinceList) == 0 {
			return 0, errors.New("数据区域权限未配置")
		}

		if len(dataAuth.ProvinceList) > 0 {
			errMsg := ""
			for _, areaItem := range areaList {
				if utils.InArray(areaItem.ItemCode, dataAuth.ProvinceList) || utils.InArray(areaItem.ParentCode, dataAuth.ProvinceList) {
					orgAreaCodes2 = append(orgAreaCodes2, areaItem.ItemCode)
				} else {
					errMsg += areaItem.ItemName + "区域未授权；"
				}
			}
			if len(errMsg) > 0 {
				return 0, errors.New(errMsg)
			}
		}
	}
	if len(orgAreaCodes2) == 0 {
		orgAreaCodes2 = orgAreaCodes
	}

	// 4. 保存数据
	orgId, err := s.orgRepo.Save(ctx, org, subOrgList, orgAreaCodes2)
	if err != nil {
		return 0, err
	}

	return orgId, nil
}

// upgradeSubOrgFullName
func (s *orgService) upgradeSubOrgFullName(ctx context.Context, orgId int64, orgFullName string) ([]*baseOrg.GfyOrganizationPo, error) {
	subOrgList, err := s.orgRepo.OrgListByParentId(ctx, orgId)
	if err != nil {
		return nil, err
	}
	for _, subOrg := range subOrgList {
		subOrg.FullName = fmt.Sprintf("%s-%s", orgFullName, subOrg.Name)
		orgList, err := s.upgradeSubOrgFullName(ctx, subOrg.Id, subOrg.FullName)
		if err != nil {
			return nil, err
		}
		if len(orgList) > 0 {
			subOrgList = append(subOrgList, orgList...)
		}
	}
	return subOrgList, nil
}

// Delete 删除组织数据并且交接工作
func (s *orgService) Delete(ctx context.Context, orgId int64) error {
	// 1. 检查部门是否存在
	org, err := s.orgRepo.GetById(ctx, orgId)
	if err != nil {
		return err
	}

	if org == nil || org.Id == 0 {
		return errcode.OrgDataNotExist
	}

	// 2. 检查部门是否还有员工
	userList, err := s.userOrgRepo.GetUsersByOrgId(ctx, orgId)
	if err != nil {
		return err
	}

	if len(userList) != 0 {
		return errcode.OrgDataHaveUser
	}

	// 3. 检查是否有子部门
	orgList, err := s.orgRepo.OrgListByParentId(ctx, orgId)
	if err != nil {
		return err
	}
	if len(orgList) != 0 {
		return errcode.OrgDataHaveDepartment
	}

	err = s.orgRepo.Delete(ctx, orgId, org.Guid)
	if err != nil {
		return err
	}

	return nil
}

// List 组织列表
func (s *orgService) List(ctx context.Context) ([]*baseOrg.OrgListItem, error) {
	list := make([]*baseOrg.OrgListItem, 0)
	orgList, err := s.orgRepo.List(ctx)
	if err != nil {
		return list, err
	}

	orgAreaList, err := s.orgRepo.OrgAreaList(ctx)
	if err != nil {
		return list, err
	}

	userResponsibleList, err := s.userOrgRepo.GetUserResponsibleList(ctx)
	if err != nil {
		return list, err
	}

	for _, o := range orgList {
		areaCodes := make([]string, 0)
		for _, orgArea := range orgAreaList {
			if o.Id == orgArea.OrganizationId {
				areaCodes = append(areaCodes, orgArea.AreaCode)
			}
		}

		userResponsible := make([]*user.UserResponsible, 0)
		for _, item := range userResponsibleList {
			if o.Id == item.OrganizationId {
				userResponsible = append(userResponsible, item)
			}
		}
		item := &baseOrg.OrgListItem{
			OrgItem:         o,
			AreaCodes:       areaCodes,
			UserResponsible: userResponsible,
		}
		list = append(list, item)
	}

	return list, nil
}

// ImportOrgs 导入组织数据
func (s *orgService) ImportOrgs(ctx context.Context, orgList []*base.ImportOrgDto) (*pb.ImportOrgResponse, error) {
	if orgList == nil || len(orgList) == 0 {
		return nil, errors.New("参数为空")
	}
	resp := &pb.ImportOrgResponse{}

	for _, orgDto := range orgList {
		orgMsg := &pb.ImportOrgMsg{}
		saveFlag := true
		orgObj := &baseOrg.GfyOrganizationPo{
			Sort:       0,
			CreatedOn:  time.Now(),
			CreatedBy:  usermetadata.GetMetaUserInfo(ctx).UserName,
			ModifiedOn: time.Now(),
			ModifiedBy: usermetadata.GetMetaUserInfo(ctx).UserName,
		}
		if orgDto.OrgFullName == "" {
			orgMsg.OrgFullName = "组织全称不能为空"
			saveFlag = false
		}
		//if orgDto.AreaNames == "" {
		//	orgMsg.AreaNames = "关联区域不能为空"
		//	saveFlag = false
		//}
		if saveFlag {
			//检查组织全称是否存在
			orgInfo, err := s.orgRepo.CheckFullNameV2(ctx, orgDto.OrgFullName)
			if err != nil {
				stark.Logger.Errorf(ctx, "ImportOrg-CheckFullNameV2 err:%+v", err)
				return nil, err
			}
			if orgInfo != nil {
				orgMsg.OrgFullName = "组织已存在"
				saveFlag = false
			} else {
				// 检查上级组织是否存在
				orgDto.OrgFullName = strings.Replace(orgDto.OrgFullName, "—", "-", -1)
				parentNames, orgName, err := utils.SplitString(orgDto.OrgFullName, "-")
				if err != nil {
					stark.Logger.Errorf(ctx, "组织全称错误,fullName", orgDto.OrgFullName)
					orgMsg.OrgFullName = "组织全称错误，集团公司已存在，不能创建集团公司"
					saveFlag = false
				} else {
					parentOrgInfo, err := s.orgRepo.CheckFullNameV2(ctx, parentNames)
					if err != nil {
						stark.Logger.Errorf(ctx, "ImportOrg-CheckFullNameV2-parent err:%+v", err)
						return nil, err
					}
					if parentOrgInfo == nil {
						orgMsg.OrgFullName = parentNames + " 不存在，请先创建 " + parentNames + " 组织"
						saveFlag = false
					} else {
						orgObj.ParentId = parentOrgInfo.Id
						orgObj.ParentGuid = parentOrgInfo.Guid
					}
					orgObj.Name = orgName
					orgObj.FullName = orgDto.OrgFullName
					orgObj.Guid = uuid.New().String()
				}
			}

			//检查关联区域是否存在
			orgAreaCodes := []string{}
			parentAreaCodes := []map[string]string{}
			if orgDto.AreaNames != "" {
				dataAuth, err := s.getDataAuthProvinceCodes(ctx)
				if err != nil {
					stark.Logger.Errorf(ctx, "ImportOrg-getDataAuthProvinceCodes err:%+v", err)
					return nil, err
				}
				if dataAuth == nil {
					stark.Logger.Errorf(ctx, "ImportOrg-getDataAuthProvinceCodes 数据权限获取异常")
					return nil, errors.New("数据权限获取异常")
				}

				if dataAuth.RegionType == 1 && orgDto.AreaNames == "全国" {
					orgAreaCodes = []string{"0"}
				} else {
					if dataAuth.RegionType == 2 && len(dataAuth.ProvinceList) == 0 {
						return nil, errors.New("数据区域权限未配置")
					}

					areaNameList := strings.Split(orgDto.AreaNames, "、")
					for _, areaName := range areaNameList {
						areaName = strings.TrimSpace(areaName)

						if areaName == "" {
							continue
						}
						areaInfo, err := s.areaConfigRepo.GetAreaInfoByLikeName(ctx, areaName, dataAuth.ProvinceList)
						if err != nil {
							stark.Logger.Errorf(ctx, "ImportOrg-GetAreaInfoByLikeName err:%+v", err)
							return nil, err
						}
						if areaInfo == nil {
							orgMsg.AreaNames += areaName + " 不在授权区域或名称不正确\n"
							saveFlag = false
						} else {
							orgAreaCodes = append(orgAreaCodes, areaInfo.ItemCode)
							if areaInfo.ParentCode != "" {
								temp := map[string]string{
									"parent_code": areaInfo.ParentCode,
									"item_code":   areaInfo.ItemCode,
								}
								parentAreaCodes = append(parentAreaCodes, temp)
							}
						}
					}
					//	过滤省、市重复数据
					if len(orgAreaCodes) > 0 && len(parentAreaCodes) > 0 {
						for _, areaCode := range orgAreaCodes {
							for _, item := range parentAreaCodes {
								if areaCode == item["parent_code"] {
									stark.Logger.Infof(ctx, "%s的所属区域：%s 与父级 %s 都在导入的区域列表中，过滤掉 %s", orgDto.OrgFullName, item["item_code"], item["parent_code"], item["item_code"])
									orgAreaCodes = removeElement(orgAreaCodes, item["item_code"])
								}
							}
						}
					}
				}
			}

			// 保存组织信息
			if saveFlag {
				orgId, err := s.orgRepo.Save(ctx, orgObj, nil, orgAreaCodes)
				if err != nil {
					stark.Logger.Errorf(ctx, "ImportOrg-info fail,orgObj:%+v, err:%+v", orgObj, err)
					orgMsg.IsSuccess = false
					orgMsg.OrgFullName = "组织保存失败"
				} else if orgId == 0 {
					stark.Logger.Errorf(ctx, "ImportOrg-info fail,orgObj:%+v, err:%+v", orgObj)
					orgMsg.IsSuccess = false
					orgMsg.OrgFullName = "组织保存失败"
				} else {
					orgMsg.IsSuccess = true
				}
			}
		}
		resp.MsgList = append(resp.MsgList, orgMsg)
	}
	resp.IsSuccess = true

	return resp, nil
}

// 获取有数据权限的省份code - 导入组织专用
// 1）读取gfyx_profit表，判断当前租户购买的产品是线索雷达还是市场洞察。如果是线索雷达，是省版还是全国版；如果是市场洞察，按全国版线索雷达逻辑处理
// 2）如果是全国版，则不限制
// 3）如果是省版，则读取gfyx_profit_province表
// 4）关联gfyx_area_config查询判断导入区域是否有授权
func (s *orgService) getDataAuthProvinceCodes(ctx context.Context) (*base.DataAuthDto, error) {
	dataAuthDto := &base.DataAuthDto{}
	// 获取产品
	profits := make([]string, 0)
	list, err := s.profitRepo.QueryAllEffectiveProfitList(ctx)
	if err != nil {
		stark.Logger.Errorf(ctx, "QueryAllEffectiveProfitList,err:", err)
		return nil, err
	}
	for _, profitItem := range list {
		if profitItem.ProfitCode == constants.ProfitClueRadarNationwide ||
			profitItem.ProfitCode == constants.ProfitMarketReport ||
			profitItem.ProfitCode == constants.ProfitClueRadarProvince ||
			profitItem.ProfitCode == constants.ProfitAIOutbound {
			profits = append(profits, profitItem.ProfitCode)
		}
		// 买了全国版线索雷达，区域类型为1
		if profitItem.ProfitCode == constants.ProfitClueRadarNationwide {
			dataAuthDto.RegionType = 1
		}
		// 买了省版线索雷达，但买全国版，区域类型为2
		if profitItem.ProfitCode == constants.ProfitClueRadarProvince && !utils.InArray(constants.ProfitClueRadarNationwide, profits) {
			dataAuthDto.RegionType = 2
		}
		// 买了市场洞察，且没有买省版线索雷达，区域类型为1
		if profitItem.ProfitCode == constants.ProfitMarketReport && !utils.InArray(constants.ProfitClueRadarProvince, profits) {
			dataAuthDto.RegionType = 1
		}
	}
	dataAuthDto.ProductList = profits
	// 仅省版线索雷达需要获取权限区域
	provinceCode := make([]string, 0)
	if dataAuthDto.RegionType == 2 {
		list, err := s.profitRepo.QueryProfitProvinceList(ctx)
		if err != nil {
			return nil, err
		}
		if list != nil {
			for _, item := range list {
				provinceCode = append(provinceCode, item.ProvinceCode)
			}
		}
	}
	dataAuthDto.ProvinceList = provinceCode

	return dataAuthDto, nil
}

func removeElement(slice []string, elementToRemove string) []string {
	var result []string
	for _, item := range slice {
		if item != elementToRemove {
			result = append(result, item)
		}
	}
	return result
}

// SyncAreaPermission 同步用户组织
func (s *orgService) SyncAreaPermission(ctx context.Context, orgGuid string, areaCodes []string, userGuids []string) error {
	// 获取组织 uid
	orgPo, err := s.orgRepo.GetByUid(ctx, orgGuid)
	if err != nil {
		return err
	}
	// 保存组织对应的区域 gfyx_organization_area_permission
	_ = s.orgRepo.SaveOrgAreasNew(ctx, orgPo.Id, "jm-sync", areaCodes)
	// 获取用户 id
	_, userList, err := s.userRepo.QueryUserList(ctx, map[string]interface{}{
		"user_guids": userGuids,
	}, nil, "")
	if err != nil {
		return err
	}
	if len(userList) > 0 {
		// 保存组织对应的负责人 gfyx_user_responsible_organization
		userIds := make([]int64, 0)
		for _, userPo := range userList {
			userIds = append(userIds, userPo.Id)
		}
		_ = s.userOrgRepo.SetDepartmentHeaderNew(ctx, userIds, orgPo.Id)
	}
	return nil
}
